/**
 * ClientConnManager.js - 客户端连接管理器
 * 管理与业务服务的TCP长连接
 */

/**
 * 客户端连接管理器
 * 管理所有业务服务连接，并按应用名分组
 */
class ClientConnManager {
  constructor() {
    // 所有客户端连接，key是clientId，value是socket
    this.connections = new Map();
    
    // 应用分组，key是appName，value是clientId的数组
    this.appGroups = new Map();
    
    // 客户端应用映射，key是clientId，value是appName
    this.clientApps = new Map();
  }
  
  /**
   * 添加一个客户端连接
   * @param {string} clientId - 客户端ID
   * @param {net.Socket} socket - 客户端socket
   */
  addConnection(clientId, socket) {
    this.connections.set(clientId, socket);
    
    console.log(`当前连接数: ${this.connections.size}`);
  }
  
  /**
   * 移除一个客户端连接
   * @param {string} clientId - 客户端ID
   */
  removeConnection(clientId) {
    // 先检查这个客户端是否注册了应用
    const appName = this.clientApps.get(clientId);
    if (appName) {
      // 从应用组中移除
      const clients = this.appGroups.get(appName) || [];
      const newClients = clients.filter(id => id !== clientId);
      
      if (newClients.length === 0) {
        // 如果应用没有任何客户端了，移除整个应用组
        this.appGroups.delete(appName);
      } else {
        this.appGroups.set(appName, newClients);
      }
      
      // 从客户端应用映射中移除
      this.clientApps.delete(clientId);
    }
    
    // 关闭并移除连接
    const socket = this.connections.get(clientId);
    if (socket) {
      socket.end();
    }
    this.connections.delete(clientId);
    
    console.log(`连接已移除，当前连接数: ${this.connections.size}`);
  }
  
  /**
   * 注册一个应用
   * @param {string} clientId - 客户端ID
   * @param {string} appName - 应用名称
   */
  registerApp(clientId, appName) {
    // 记录客户端关联的应用
    this.clientApps.set(clientId, appName);
    
    // 将客户端添加到应用组
    let clients = this.appGroups.get(appName);
    if (!clients) {
      clients = [];
      this.appGroups.set(appName, clients);
    }
    
    // 确保不重复添加
    if (!clients.includes(clientId)) {
      clients.push(clientId);
    }
    
    console.log(`客户端 ${clientId} 注册到应用 ${appName}，该应用当前客户端数：${clients.length}`);
  }
  
  /**
   * 推送热键到指定应用的所有客户端
   * @param {string} appName - 应用名称
   * @param {Object} hotKeyModel - 热键模型
   */
  pushToApp(appName, hotKeyModel) {
    const clients = this.appGroups.get(appName) || [];
    
    if (clients.length === 0) {
      console.log(`应用 ${appName} 没有连接的客户端，无法推送热键`);
      return;
    }
    
    const message = JSON.stringify({
      type: 'hotkey',
      data: hotKeyModel
    });
    
    let successCount = 0;
    
    for (const clientId of clients) {
      const socket = this.connections.get(clientId);
      if (socket && socket.writable) {
        try {
          socket.write(message);
          successCount++;
        } catch (err) {
          console.error(`向客户端 ${clientId} 推送热键失败:`, err);
          // 错误处理：可能需要移除此连接
          this.removeConnection(clientId);
        }
      }
    }
    
    console.log(`向应用 ${appName} 推送热键 ${hotKeyModel.key}，成功：${successCount}/${clients.length}`);
  }
  
  /**
   * 向所有连接的客户端推送热键
   * @param {Object} hotKeyModel - 热键模型
   */
  pushToAll(hotKeyModel) {
    const message = JSON.stringify({
      type: 'hotkey',
      data: hotKeyModel
    });
    
    let successCount = 0;
    
    for (const [clientId, socket] of this.connections.entries()) {
      if (socket && socket.writable) {
        try {
          socket.write(message);
          successCount++;
        } catch (err) {
          console.error(`向客户端 ${clientId} 推送热键失败:`, err);
          // 错误处理：可能需要移除此连接
          this.removeConnection(clientId);
        }
      }
    }
    
    console.log(`向所有客户端推送热键 ${hotKeyModel.key}，成功：${successCount}/${this.connections.size}`);
  }
  
  /**
   * 推送删除热键的消息到指定应用的所有客户端
   * @param {string} appName - 应用名称
   * @param {Object} hotKeyModel - 热键模型
   */
  removeFromApp(appName, hotKeyModel) {
    const clients = this.appGroups.get(appName) || [];
    
    if (clients.length === 0) {
      console.log(`应用 ${appName} 没有连接的客户端，无法推送删除热键`);
      return;
    }
    
    const message = JSON.stringify({
      type: 'remove_hotkey',
      data: hotKeyModel
    });
    
    let successCount = 0;
    
    for (const clientId of clients) {
      const socket = this.connections.get(clientId);
      if (socket && socket.writable) {
        try {
          socket.write(message);
          successCount++;
        } catch (err) {
          console.error(`向客户端 ${clientId} 推送删除热键失败:`, err);
          this.removeConnection(clientId);
        }
      }
    }
    
    console.log(`向应用 ${appName} 推送删除热键 ${hotKeyModel.key}，成功：${successCount}/${clients.length}`);
  }
}

module.exports = ClientConnManager;